<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <p>{{count}}</p>
        <p>
            <button @click="addCount">count++</button>
        </p>
        <hr>
        <p>{{zhang.name}}---{{zhang.age}}</p>
        <p>{{zhang.hobby}}</p>
        <p>{{zhang.grade}}</p>
        <p>
            <button @click="changeAge">changeAge</button>
            <button @click="changeChinese">changeChinese</button>
        </p>



    </div>
</body>
<script type="module">
    // 整体载入  => 查看模块内暴露的变量和方法
    import * as Vue from "../js/vue.esm-browser.js";
    console.log(Vue);

    // 按需引入
    import { createApp, ref, reactive, readonly, computed, watch } from "../js/vue.esm-browser.js";


    // 组合式写法 可以理解为是选项式语法的优化, 但是最终还是会被解析成选项式语法
    // 在 setup() 函数中返回的对象会暴露给模板和组件实例。其他的选项也可以通过组件实例来获取 setup() 暴露的属性
    let app = createApp({
        setup() {

            /* 
                watch()​
                    侦听一个或多个响应式数据源，并在数据源变化时调用所给的回调函数(执行副作用操作)。

                用法
                watch(source,callback)   侦听一个数据源
                    source  监听的数据(ref对象 计算属性(computedRef)  getter函数)
                    callback   数据源变化时调用所给的回调函数

                watch([source,source,source],callback)   侦听多个数据源(只要数组中的某一个数据源改变,都会触发回调函数)
                    [source,source,source]  监听的数据的数组
                    callback   数据源变化时调用所给的回调函数


                
            
            */
            let count = ref(1);
            let doubleCount = computed(() => {
                return count.value * 2
            })

            let zhang = reactive({
                name: "张三",
                age: 18,
                hobby: ["唱", "跳", "rap"],
                grade: {
                    chinese: 55,
                    math: 66,
                    english: 77,
                },
            })

            const changeAge = () => {
                zhang.age++;
            }

            const changeChinese = () => {
                zhang.grade.chinese++;
            }

            const addCount = () => {
                count.value++;
            }


            // 监听ref对象
            // watch(count,function(newVal,oldVal){
            //     console.log("count改变了",newVal,oldVal);
            // })

            // 监听计算属性(ref对象)
            // watch(doubleCount,function(newVal,oldVal){
            //     console.log("doubleCount改变了",newVal,oldVal);
            // })

            // 监听getter函数 (getter函数返回的值,就是要监听的数据)
            // 可以理解为 1. 先通过此函数生成一个计算属性, 2. 在监听计算属性是否更改
            // 监听count是否改变
            // watch(()=>count.value,function(newVal,oldVal){
            //     console.log("count改变了",newVal,oldVal);
            // })

            // 监听zhang.name是否改变
            // watch(()=>zhang.age,function(newVal,oldVal){
            //     console.log("zhang.age改变了",newVal,oldVal);
            // })

            // 等价于
            // let age = computed(()=>zhang.age);
            // watch(age,function(newVal,oldVal){
            //     console.log("zhang.age改变了",newVal,oldVal);
            // })


            // 监听多个数据源
            watch([count, doubleCount, () => zhang.name, () => zhang.age], function (newVal, oldVal) {
                console.log("newVal", newVal);
                console.log("oldVal", oldVal);
            })






            return {
                count,
                zhang,
                changeAge,
                changeChinese,
                addCount,
            }

        },
        mounted() {
            console.log("mounted", this);

            /* 
                this => 当前vue实例的Proxy代理对象(模拟)
                Proxy => {   // 写法只是方便理解
                    get a(){
                        return a.value;
                    }
                    set a(val){
                        a.value = val;
                    }
                }

            
            
            */
        },
    })

    app.mount("#app");
</script>

</html>